-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Emit & Dyn_emit now wrap string.format + Vector instruction segment fix #27
Emit & Dyn_emit now wrap string.format + Vector instruction segment fix #27
Conversation
lua/wire/zvm/zvm_opcodes.lua
Outdated
if not self.EmitOperandSegment[1] then | ||
seg1code = "VM.DS" | ||
end | ||
if not self.EmitOperandSegment[2] then | ||
seg2code = "VM.DS" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't seg1code and seg2code be self.EmitOperandSegment[1]
and self.EmitOperandSegment[2]
if they are set?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EmitOperandSegment needs to be checked for validity if that's the case otherwise it still poses a threat.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is for fixing #26, which is that if they have a segment set it would add the segment to it twice, because if say, FS = 6 and R0 = 2, passing FS:R0 to these instructions is the same as passing 8, but these instructions expect it to just be the value of R0 rather than the value of FS + R0, so it would end up trying to load a vector from memory index 14(6+8) rather than index 8(6+2)
The only time this isn't the case is when a segment isn't used, where it instead defaults to adding VM.DS, because the value of the operand isn't getting segment added to it by default, so I default it to adding 0 if there's a segment in that spot to avoid adding it twice without breaking the functionality of non-memory uses of segment:reg offsetting, because reading variables in functions use this trick(they do RSTACK REG,EBP:const a lot for 3 byte access that doesn't modify the ptr register)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh okay, makes sense
Looks like an improvement, but is a huge cost to performance as well. I'd like to see the 'Emit' shit replaced with actual lua rather than string-building into compiled lua code at some point. This is fine for now at least. |
lua/wire/zvm/zvm_opcodes.lua
Outdated
local seg1code,seg2code = "0","0" | ||
if not self.EmitOperandSegment[1] then | ||
seg1code = "VM.DS" | ||
end | ||
if not self.EmitOperandSegment[2] then | ||
seg2code = "VM.DS" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could these all be changed to this?
local seg1code = self.EmitOperandSegment[1] and "0" or "VM.DS"
local seg2code = self.EmitOperandSegment[2] and "0" or "VM.DS"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like that works, so sure, I'll get a commit for it in a moment.
I have been wondering if there may be a performance improvement in reducing the number of calls to string format and global emit/dyn_emit, by possibly replacing them with a version that builds a smaller, local string(saving the arguments), then calling the global emit at the end which will run string.format once on the whole instruction's code rather than string.formatting and concatenating to the entire block on every emit/dyn_emit I'd like to ask others that are more familiar with lua's performance regarding the local part, but I imagine less frequent (but bigger) calls to string.format would go a long way |
Yeah the less concats and formats, the better. |
You could potentially combine a bunch of those groups of emits into a single emit. |
Didn't realize it ran at runtime. That is pretty terrible. Then again the emit function itself is very laggy just looking at the code. It uses repeated string concatenation so a If it were me I'd refactor it to store it properly as a string buffer and only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should change this emit function too, no?
wire-cpu/lua/wire/zvm/zvm_core.lua
Line 28 in 39b3a4b
function ZVM:Emit(text) |
@Vurv78 That one can only occur if microcodedebug is on, the only condition that sets it is if not SERVER and not CLIENT, I don't know if such a state is possible unless you're running it outside of gmod, or manually assigning it |
I'm fairly certain these will only run on compile/precompile, I.E that section is only encountered for the first time and hasn't been modified by the CPU itself I've noticed that you can tell easily when something like the GPU is starting a precompile by it flashing the "took too long to draw frame!" the first time you enter a new block.
If you think this'll help I can do it. |
Then if it's unused you could remove it or add a comment saying so and leave it for later |
If it's not runtime then it doesn't really matter, so up to you. I just skimmed over the code because @thegrb93 said it'd be a perf hit. I did initially think it only ran to compile once |
I should probably test to check if the emits are run every time, or if they only build a precompiled block, I'm fairly certain it's only while building a precompiled block but it would also be good to see how frequently blocks get precompiled to see how big a hit to performance this may result in. |
They are precompiled blocks, but it explains the tons of lag you get when initially placing a cpu |
I've got a basic test to measure the amount of time spent in the precompile functions on two separate branches, one before these changes, and one after these changes Confirm for yourselves using these two branches |
I wasn't concerned with a huge latency increase, just knew it would be slightly more expensive. I imagine most of the latency is from reallocations. |
I think vurv just wants a comment added to that emit function and this can be merged. |
Marked them all w/ a comment |
…egment fix (wiremod#27)" This reverts commit 52f9dcc.
May fix #26 for vector instructions, tested with VADD but needs further testing on the other VEXP instructions.
Implements @Vurv78's suggestion for ZVM:Emit() and ZVM:Dyn_Emit(), since they take strings, making them wrap string.format() to stop concatenating strings and numbers in a potentially unsafe manner.
Converts all known calls to dyn_emit and emit that concatenate numbers in zvm_opcodes and gmod_wire_cpu to use %d
Dyn_EmitOperand remains unaffected at the moment due to taking multiple args already